use super::*;
use tempfile::TempDir;
use std::sync::Arc;

/// Test configuration manager basic operations
#[tokio::test]
async fn test_config_manager_basic_operations() {
    let manager = ConfigManager::with_memory_storage();
    manager.initialize().await.unwrap();
    
    // Test getting default value
    let font_size = manager.get_value("editor.font_size").await.unwrap();
    assert_eq!(font_size, Some(serde_json::Value::Number(14.into())));
    
    // Test setting value
    manager.set_value("editor.font_size", serde_json::Value::Number(16.into())).await.unwrap();
    
    let updated_font_size = manager.get_value("editor.font_size").await.unwrap();
    assert_eq!(updated_font_size, Some(serde_json::Value::Number(16.into())));
    
    // Test getting entire config
    let config = manager.get_config().await;
    assert_eq!(config.editor.font_size, 16);
}

/// Test configuration change notifications
#[tokio::test]
async fn test_config_change_notifications() {
    let manager = ConfigManager::with_memory_storage();
    manager.initialize().await.unwrap();
    
    let mut receiver = manager.subscribe_to_changes();
    
    // Set a value and check for notification
    manager.set_value("editor.font_size", serde_json::Value::Number(18.into())).await.unwrap();
    
    let change_event = receiver.recv().await.unwrap();
    assert_eq!(change_event.key, "editor.font_size");
    assert_eq!(change_event.new_value, serde_json::Value::Number(18.into()));
}

/// Test configuration reset functionality
#[tokio::test]
async fn test_config_reset() {
    let manager = ConfigManager::with_memory_storage();
    manager.initialize().await.unwrap();
    
    // Change a value
    manager.set_value("editor.font_size", serde_json::Value::Number(20.into())).await.unwrap();
    
    // Reset to defaults
    manager.reset_to_defaults().await.unwrap();
    
    // Check that value is back to default
    let font_size = manager.get_value("editor.font_size").await.unwrap();
    assert_eq!(font_size, Some(serde_json::Value::Number(14.into())));
}

/// Test configuration section reset
#[tokio::test]
async fn test_config_section_reset() {
    let manager = ConfigManager::with_memory_storage();
    manager.initialize().await.unwrap();
    
    // Change multiple editor values
    manager.set_value("editor.font_size", serde_json::Value::Number(20.into())).await.unwrap();
    manager.set_value("editor.tab_size", serde_json::Value::Number(8.into())).await.unwrap();
    
    // Reset only editor section
    manager.reset_section("editor").await.unwrap();
    
    // Check that editor values are back to defaults
    let font_size = manager.get_value("editor.font_size").await.unwrap();
    let tab_size = manager.get_value("editor.tab_size").await.unwrap();
    assert_eq!(font_size, Some(serde_json::Value::Number(14.into())));
    assert_eq!(tab_size, Some(serde_json::Value::Number(4.into())));
}

/// Test file-based configuration storage
#[tokio::test]
async fn test_file_config_storage() {
    let temp_dir = TempDir::new().unwrap();
    let config_path = temp_dir.path().join("test_config.json");
    
    let storage = FileConfigStorage::new(config_path.clone()).unwrap();
    
    // Test loading default config when file doesn't exist
    let config = storage.load().await.unwrap();
    assert_eq!(config.version, "1.0.0");
    
    // Test saving config
    let mut config = AppConfig::default();
    config.editor.font_size = 16;
    storage.save(&config).await.unwrap();
    
    // Test loading saved config
    let loaded_config = storage.load().await.unwrap();
    assert_eq!(loaded_config.editor.font_size, 16);
    
    // Test backup creation
    let backup_path = storage.create_backup().await.unwrap();
    assert!(backup_path.exists());
    
    // Test backup listing
    let backups = storage.list_backups().await.unwrap();
    assert_eq!(backups.len(), 1);
}

/// Test configuration migration
#[test]
fn test_config_migration() {
    let manager = ConfigMigrationManager::default();
    
    // Test configuration that needs migration
    let mut config = serde_json::json!({
        "version": "0.1.0",
        "editor": {
            "fontSize": 14,
            "tabSize": 4
        },
        "appearance": {
            "theme": "dark"
        }
    });
    
    assert!(manager.needs_migration(&config).unwrap());
    
    let result = manager.migrate_config(&mut config).unwrap();
    assert_eq!(result.original_version, "0.1.0");
    assert_eq!(result.final_version, "1.0.0");
    assert_eq!(result.applied_migrations.len(), 2);
    
    // Check that fields were migrated correctly
    assert_eq!(config["editor"]["font_size"], 14);
    assert_eq!(config["editor"]["tab_size"], 4);
    assert_eq!(config["appearance"]["theme"], "Dark");
    assert!(config["performance"].is_object());
    assert!(config["advanced"].is_object());
}

/// Test configuration backup and restore
#[test]
fn test_config_backup_restore() {
    let temp_dir = TempDir::new().unwrap();
    let backup_manager = ConfigBackupManager::new(temp_dir.path().to_path_buf(), 5).unwrap();
    
    let config = AppConfig::default();
    
    // Test creating backup
    let backup_info = backup_manager.create_auto_backup(&config).unwrap();
    assert!(backup_info.path.exists());
    
    // Test listing backups
    let backups = backup_manager.list_backups().unwrap();
    assert_eq!(backups.len(), 1);
    
    // Test restoring backup
    let restored_config = backup_manager.restore_backup(&backup_info.path).unwrap();
    assert_eq!(restored_config.version, config.version);
    
    // Test backup stats
    let stats = backup_manager.get_backup_stats().unwrap();
    assert_eq!(stats.total_count, 1);
    assert!(stats.total_size > 0);
}

/// Test workspace state serialization
#[test]
fn test_workspace_state_serialization() {
    let state = WorkspaceState::default();
    
    // Test JSON serialization
    let json = serde_json::to_string(&state).unwrap();
    let deserialized: WorkspaceState = serde_json::from_str(&json).unwrap();
    
    assert_eq!(state.metadata.version, deserialized.metadata.version);
    assert_eq!(state.open_files.len(), deserialized.open_files.len());
}

/// Test workspace state validation
#[test]
fn test_workspace_state_validation() {
    let mut state = WorkspaceState::default();
    state.metadata.name = "Test Workspace".to_string();
    
    let result = serialization::validate_state(&state);
    assert!(result.is_valid);
    assert!(result.errors.is_empty());
}

/// Test workspace state manager
#[tokio::test]
async fn test_workspace_state_manager() {
    let temp_dir = TempDir::new().unwrap();
    let workspace_path = temp_dir.path().to_path_buf();
    
    let manager = WorkspaceStateManager::with_workspace_path(&workspace_path).unwrap();
    
    let mut state = WorkspaceState::default();
    state.metadata.name = "Test Workspace".to_string();
    state.metadata.root_path = workspace_path.clone();
    
    // Test saving and loading
    manager.save_state(&state).await.unwrap();
    let loaded_state = manager.load_state().await.unwrap();
    
    assert_eq!(state.metadata.name, loaded_state.metadata.name);
    assert_eq!(state.metadata.root_path, loaded_state.metadata.root_path);
}

/// Test platform configuration compatibility
#[test]
fn test_platform_config_compatibility() {
    let config = AppConfig::default();
    let result = platform::PlatformConfig::is_compatible(&config);
    
    // Should be compatible with default config
    assert!(result.is_compatible);
}

/// Test platform configuration adjustments
#[test]
fn test_platform_config_adjustments() {
    let mut config = AppConfig::default();
    
    // Apply platform adjustments
    platform::PlatformConfig::adjust_for_platform(&mut config).unwrap();
    
    // Check that adjustments were applied
    assert!(config.performance.worker_threads > 0);
}

/// Test configuration export and import
#[tokio::test]
async fn test_config_export_import() {
    let manager = ConfigManager::with_memory_storage();
    manager.initialize().await.unwrap();
    
    // Modify configuration
    manager.set_value("editor.font_size", serde_json::Value::Number(18.into())).await.unwrap();
    
    // Export configuration
    let exported = manager.export_config().await.unwrap();
    
    // Reset configuration
    manager.reset_to_defaults().await.unwrap();
    
    // Import configuration
    manager.import_config(&exported).await.unwrap();
    
    // Check that imported value is correct
    let font_size = manager.get_value("editor.font_size").await.unwrap();
    assert_eq!(font_size, Some(serde_json::Value::Number(18.into())));
}

/// Test configuration validation
#[test]
fn test_config_validation() {
    let config = serde_json::json!({
        "version": "1.0.0",
        "editor": {},
        "appearance": {},
        "files": {}
    });
    
    let result = ConfigCompatibilityChecker::check_compatibility(&config);
    assert!(result.is_compatible);
    assert!(result.issues.is_empty());
}

/// Test configuration paths
#[test]
fn test_config_paths() {
    // Test that config paths can be retrieved
    let config_dir = ConfigPaths::config_dir().unwrap();
    let data_dir = ConfigPaths::data_dir().unwrap();
    let cache_dir = ConfigPaths::cache_dir().unwrap();
    
    assert!(!config_dir.as_os_str().is_empty());
    assert!(!data_dir.as_os_str().is_empty());
    assert!(!cache_dir.as_os_str().is_empty());
}

/// Test path normalization
#[test]
fn test_path_normalization() {
    let path = PathBuf::from("test/path/with/forward/slashes");
    let normalized = ConfigPaths::normalize_path(&path);
    
    if cfg!(target_os = "windows") {
        assert!(normalized.to_string_lossy().contains('\\'));
    } else {
        assert!(normalized.to_string_lossy().contains('/'));
    }
}

/// Integration test for complete configuration workflow
#[tokio::test]
async fn test_complete_config_workflow() {
    let temp_dir = TempDir::new().unwrap();
    let config_path = temp_dir.path().join("workflow_test.json");
    
    // Create manager with file storage
    let storage = Arc::new(FileConfigStorage::new(config_path).unwrap());
    let manager = ConfigManager::new(storage);
    
    // Initialize and modify configuration
    manager.initialize().await.unwrap();
    manager.set_value("editor.font_size", serde_json::Value::Number(20.into())).await.unwrap();
    manager.set_value("appearance.theme", serde_json::Value::String("Dark".to_string())).await.unwrap();
    
    // Create backup
    let backup_path = manager.create_backup().await.unwrap();
    assert!(backup_path.exists());
    
    // Reset and restore
    manager.reset_to_defaults().await.unwrap();
    manager.restore_backup(&backup_path).await.unwrap();
    
    // Verify restored values
    let font_size = manager.get_value("editor.font_size").await.unwrap();
    let theme = manager.get_value("appearance.theme").await.unwrap();
    
    assert_eq!(font_size, Some(serde_json::Value::Number(20.into())));
    assert_eq!(theme, Some(serde_json::Value::String("Dark".to_string())));
}
